package com.test.study.web;

import com.test.study.anno.RpcService;
import com.test.study.pojo.GpRpcReq;
import com.test.study.pojo.GpRpcResp;
import com.test.study.protocol.GpReqDecoder;
import com.test.study.protocol.GpRespEncoder;
import com.test.study.registry.AbstractRegistryWith;
import com.test.study.registry.RegistryWith;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class GpRpcServer implements ApplicationContextAware,InitializingBean {
	
	private int port;
//	private ExecutorService serverPool = Executors.newCachedThreadPool();
	private ConcurrentHashMap<String,Object> services=new ConcurrentHashMap<>();
	private RegistryWith registryWith = new AbstractRegistryWith();
	
	public GpRpcServer(int port) {
		super();
		this.port = port;
	}


	public int getPort() {
		return port;
	}


	public void setPort(int port) {
		this.port = port;
	}
	/**
	 * 加载application ,初始化，以后 发布服务
	 */
	@Override
	public void afterPropertiesSet() throws Exception {

		NioEventLoopGroup boosGrup = new NioEventLoopGroup();
		NioEventLoopGroup workGroup = new NioEventLoopGroup();
		ServerBootstrap bootstrap = new ServerBootstrap();

		try {
			bootstrap.group(boosGrup,workGroup)
					.channel(NioServerSocketChannel.class)
					.childHandler(new ChannelInitializer<SocketChannel>() {
						@Override
						protected void initChannel(SocketChannel ch) throws Exception {
							ChannelPipeline pipeline = ch.pipeline();
//							pipeline.addLast(new ObjectDecoder(Integer.MAX_VALUE,
//											ClassResolvers.cacheDisabled
//													(null)));
//							pipeline.addLast(new ObjectEncoder());
							pipeline.addLast(new GpReqDecoder(GpRpcReq.class));
							pipeline.addLast(new GpRespEncoder(GpRpcResp
									.class));
							pipeline.addLast(new ProcessorHandler(services));
						}
					})
					// 针对主线程的配置 分配线程最大数量 128
					.option(ChannelOption.SO_BACKLOG, 128)
					// 针对子线程的配置 保持长连接
					.childOption(ChannelOption.SO_KEEPALIVE, true);
			ChannelFuture future = bootstrap.bind(port).sync();
			future.channel().closeFuture().sync();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally {
			workGroup.shutdownGracefully();
			boosGrup.shutdownGracefully();
		}

//		ServerSocket serverSocket = null;
//		try {
//			serverSocket = new ServerSocket(port);
//			System.out.println("gprpc has started at port:"+port);
//			while(true){
//				Socket accept = serverSocket.accept();
//				serverPool.submit(new GpRpcServerHandler(accept,services));
//			}
//		} catch (IOException e) {
//			e.printStackTrace();
//		}finally{
//			if(null != serverSocket){
//				try {
//					serverSocket.close();
//				} catch (IOException e) {
//					e.printStackTrace();
//				}
//			}
//		}
	}


	@Override
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		Map<String, Object> beans = applicationContext.getBeansWithAnnotation(RpcService.class);
		if(!beans.isEmpty()){
			for(Object bean:beans.values()){
				RpcService annotation = bean.getClass().getAnnotation(RpcService.class);
				String serviceName = annotation.className().getName();
				if(annotation.ver()!=null&&!"".equals(annotation.ver())){
					serviceName= annotation.className().getName()+"_"+annotation.ver();
				}
				services.put(serviceName, bean);
				registryWith.registry(serviceName,getAddess()+":"+port);
				
			}
		}
	}

	/**
	 * Title 获取本地的ip
	 * @Author zj
	 * @Date 2019/7/12 15:21
	 * @Param
	 * @Return java.lang.String
	 */
	private String getAddess() {
		InetAddress inetAddress = null;
		try {
			inetAddress = InetAddress.getLocalHost();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
		return inetAddress.getHostAddress();
	}

}
